ALV-Grid und Dropdown
Es gibt einige Verhaltensweise in SAP-Objekten, bei denen ich einfach nicht verstehe, warum diese nicht schon seit langer Zeit behoben wurden. Eine dieser Missstände ist, dass im Eingabebereiten ALV-Grid Felder nicht leer gelassen werden können, wenn an der Domäne Festwerte definiert sind und zu den Festwerten kein SPACE gehört. Dann sieht es so aus:
Ein anderes Phänomen sind für mich die Drop-Down-Listen, oder auch Listboxen oder Auswahllisten. Hier gibt es zwei Varianten:
- Variante A: nur mit dem internen Feldwert
- Variante B: Alias, die einen internen Feldwert und eine Bezeichnung erlaubt
Variante A ist fast immer nutzlos, denn in den seltensten Fällen möchte man nur den internen Wert in der Auswahlhilfe sehen. Hier ein Beispiel im Feld “Status”:
Variante B mit dem Alias ist bereits hilfreicher, denn der Anwender kann bei der Auswahl der Werte erkennen, was der Wert bedeutet. Hier ein Beispiel im Feld “Fruit”:
Hier ist für mich jedoch das Manko, dass nach Auswahl der Bezeichner nicht mehr zu sehen ist. Zudem wird der interne Wert in der Drop-Down-Liste nicht angezeigt, wenn man ihn nicht explizit mit einprogrammiert.
Beide Varianten unterscheiden sich somit von den Listboxen, die man vom Dynpro kennt. Hier kann man den beschreibenden Text nicht nur bei der Eingabe sehen:
Sondern auch nach der Auswahl:
Im SAPGUI kannst du noch einstellen, ob du den Schlüsselwert sehen möchtest oder nicht:
Das ist eine sinnvolle Darstellung von Listboxen.
Drop-Down-Liste und Festwerte
Für das ALV-Grid gibt es meines Wissens keine einfache Alternative um ein Feld als Listbox im Feldkatalog zu definieren, so dass vorhandene Festwerte direkt und ohne weiteres Zutun in der Drop-Down-Liste angezeigt werden.
Alternativen
Jedes Mal auf’s Neue kann ich nicht glaube, dass es im ALV-Grid keine andere Möglichkeit gibt, also habe ich mir folgende Alternativen überlegt. Beide Alternativen arbeiten mit einem zusätzlichen Feld.
- Auswahl Schlüsselfeld und Beschreibung in separates Feld
- Auswahl Textfeld und Ermittlung der ID
Beide Varianten bedeuten mehr Aufwand, denn du musst das Ereignis DATA_CHANGED registrieren und ausprogrammieren. Sie bedeuten jedoch für den Anwender auch einen größeren Bedienkomfort.
Leider habe ich noch keine Möglichkeit gefunden, dass der Text sofort nach Auswahl aktualisiert wird. Der Anwender muss in jedem Fall eine Taste drücken oder in ein anderes Feld klicken.
Auswahl Schlüsselfeld
Ich definiere für die Ausgabe ein separates Feld, das den Bezeichner des zugehörigen Feldes aufnimmt. In diesem Beispiel das Feld “Hardware-ID”:
Ich verwende die Drop-Down-Alias-Variante. Zusätzlich wird im Ereignis CL_GUI_ALV_GRID-DATA_CHANGED der Feldwert ausgelesen und mittels MODIFY_CELL in das zugehöriger Bezeichnerfeld geschrieben.
Auswahl Textfeld
In dieser Variante definiere ich die Drop-Drown-Liste für das Beschreibungsfeld und ermittle aus der Beschreibung den internen Schlüssel:
Fazit
Welche Variante du verwendest, musst du selbst entscheiden. Meiner Meinung nach ist die erste Variante einen Tick einfacher, da hier bei dem internen Feldwert der richtige interne Wert direkt mitgegeben werden kann und so der Text zur ID ermittelt wird. Bei der zweiten Variante wird die ID zum Text ermittelt, was eher ungewöhnlich ist.
Vorteil der zweiten Variante ist, dass das Schlüsselfeld mit dem internen Wert einfach versteckt werden kann und so für den Benutzer gar nicht sichtbar ist. Der Benutzer sieht also nur den Wert, der in der Regel auch sprechend und sinnvoll für ihn ist.
In beiden Fällen muss sichergestellt werden, dass interner Wert und externe Beschreibung immer zueinander passen und korrekt ermittelt werden.
Code
REPORT. PARAMETERS p_hwid TYPE c LENGTH 1 AS LISTBOX VISIBLE LENGTH 20. CLASS main DEFINITION. PUBLIC SECTION. TYPES: BEGIN OF _line, id TYPE c LENGTH 1, text TYPE c LENGTH 20, END OF _line, _tab TYPE SORTED TABLE OF _line WITH UNIQUE KEY id. TYPES: BEGIN OF _data_line, key TYPE c LENGTH 2, status TYPE c LENGTH 1, "Dropdown fruit TYPE c LENGTH 1, "Dropdown Alias hardware TYPE c LENGTH 1, "Dropdown Alias + separate text field hw_text TYPE c LENGTH 20, weekday_id TYPE c LENGTH 1, weekday_txt TYPE c LENGTH 20, END OF _data_line, _data_table TYPE STANDARD TABLE OF _data_line WITH EMPTY KEY. CLASS-DATA hw_ids TYPE _tab. CLASS-DATA weekday_ids TYPE _tab. METHODS constructor. CLASS-METHODS class_constructor. METHODS display IMPORTING container TYPE REF TO cl_gui_container. PRIVATE SECTION. DATA datatable TYPE _data_table. DATA grid TYPE REF TO cl_gui_alv_grid. DATA dropdown TYPE lvc_t_drop. DATA dropdown_alias TYPE lvc_t_dral. CONSTANTS dd_handle_status TYPE i VALUE 1. CONSTANTS dd_handle_fruit TYPE i VALUE 2. CONSTANTS dd_handle_hw TYPE i VALUE 3. CONSTANTS dd_handle_weekday TYPE i VALUE 4. METHODS on_data_changed FOR EVENT data_changed OF cl_gui_alv_grid IMPORTING e_onf4 e_onf4_after e_onf4_before e_ucomm er_data_changed. METHODS get_fcat RETURNING VALUE(result) TYPE lvc_t_fcat. ENDCLASS. CLASS main IMPLEMENTATION. METHOD class_constructor. hw_ids = VALUE #( ( id = 'X' text = 'Tablet' ) ( id = 'Y' text = 'Personal Computer' ) ( id = 'Z' text = 'Laptop' ) ). weekday_ids = VALUE #( ( id = '1' text = 'Monday' ) ( id = '2' text = 'Tuesday' ) ( id = '3' text = 'Wednesday' ) ( id = '4' text = 'Thursday' ) ( id = '5' text = 'Friday' ) ( id = '6' text = 'Saturday' ) ( id = '7' text = 'Sunday' ) ). ENDMETHOD. METHOD constructor. "Simple Dropdown: STATUS dropdown = VALUE #( handle = dd_handle_status ( value = '1' ) ( value = '2' ) ( value = '3' ) ). "Dropdown-Alias: FRUITS dropdown_alias = VALUE #( handle = dd_handle_fruit ( int_value = 'A' value = 'Apple' ) ( int_value = 'B' value = 'Banana' ) ( int_value = 'C' value = 'Coconut' ) ). "Dropdown-Alias with description field: HARDWARE APPEND LINES OF VALUE lvc_t_dral( FOR l_hw IN hw_ids ( handle = dd_handle_hw int_value = l_hw-id value = l_hw-text ) ) TO dropdown_alias. "Dropdown-Alias with description selection: WEEKDAY APPEND LINES OF VALUE lvc_t_dral( FOR l_wd IN weekday_ids ( handle = dd_handle_weekday int_value = l_wd-text value = l_wd-text ) ) TO dropdown_alias. "fill demo data in internal table datatable = VALUE #( ( key = '10' status = '1' fruit = 'A' hardware = 'X' weekday_id = '3' ) ( key = '20' ) ( key = '30' ) ). ENDMETHOD. METHOD display. grid = NEW #( i_parent = container ). DATA(fcat) = get_fcat( ). LOOP AT datatable ASSIGNING FIELD-SYMBOL(<data>). IF <data>-hardware IS NOT INITIAL. <data>-hw_text = dropdown_alias[ handle = dd_handle_hw int_value = <data>-hardware ]-value. <data>-weekday_txt = weekday_ids[ id = <data>-weekday_id ]-text. ENDIF. ENDLOOP. grid->set_drop_down_table( it_drop_down = dropdown it_drop_down_alias = dropdown_alias ). grid->set_table_for_first_display( CHANGING it_outtab = datatable it_fieldcatalog = fcat EXCEPTIONS OTHERS = 4 ). IF sy-subrc > 0. RETURN. ENDIF. SET HANDLER on_data_changed FOR grid. grid->register_edit_event( cl_gui_alv_grid=>mc_evt_modified ). ENDMETHOD. METHOD get_fcat. result = VALUE #( tabname = '1' datatype = 'CHAR' ( fieldname = 'KEY' outputlen = 10 intlen = 2 drdn_hndl = 0 drdn_alias = ' ' reptext = 'Key' edit = ' ' ) ( fieldname = 'STATUS' outputlen = 10 intlen = 1 drdn_hndl = dd_handle_status drdn_alias = ' ' reptext = 'Status' edit = 'X' ) ( fieldname = 'FRUIT' outputlen = 10 intlen = 1 drdn_hndl = dd_handle_fruit drdn_alias = 'X' reptext = 'Fruit' edit = 'X' ) ( fieldname = 'HARDWARE' outputlen = 10 intlen = 1 drdn_hndl = dd_handle_hw drdn_alias = 'X' reptext = 'Hardware-ID' edit = 'X' ) ( fieldname = 'HW_TEXT' outputlen = 30 intlen = 20 drdn_hndl = 0 drdn_alias = ' ' reptext = 'Hardware descr.' edit = ' ' ) ( fieldname = 'WEEKDAY_ID' outputlen = 10 intlen = 1 drdn_hndl = 0 drdn_alias = ' ' reptext = 'Weekday ID' edit = ' ' ) ( fieldname = 'WEEKDAY_TXT' outputlen = 20 intlen = 20 drdn_hndl = dd_handle_weekday drdn_alias = 'X' reptext = 'Weekday' edit = 'X' lowercase = 'X') ). ENDMETHOD. METHOD on_data_changed. DATA text TYPE string. LOOP AT er_data_changed->mt_good_cells INTO DATA(cell). CASE cell-fieldname. WHEN 'HARDWARE'. text = COND #( WHEN cell-value IS INITIAL THEN `` ELSE dropdown_alias[ handle = dd_handle_hw int_value = cell-value ]-value ). er_data_changed->modify_cell( i_row_id = cell-row_id i_tabix = cell-tabix i_fieldname = 'HW_TEXT' i_value = text ). WHEN 'WEEKDAY_TXT'. text = COND #( WHEN cell-value IS INITIAL THEN `` ELSE weekday_ids[ text = cell-value ]-id ). er_data_changed->modify_cell( i_row_id = cell-row_id i_tabix = cell-tabix i_fieldname = 'WEEKDAY_ID' i_value = text ). ENDCASE. ENDLOOP. ENDMETHOD. ENDCLASS. INITIALIZATION. DATA(docker) = NEW cl_gui_docking_container( side = cl_gui_docking_container=>dock_at_bottom ratio = 80 ). DATA(app) = NEW main( ). app->display( docker ). CALL FUNCTION 'VRM_SET_VALUES' EXPORTING id = 'P_HWID' values = CORRESPONDING vrm_values( main=>hw_ids MAPPING key = id text = text ).
- 7. December: Excel Racing Simulation – Root Vole Race - 7. Dezember 2024
- 5. December: ABAPConf - 5. Dezember 2024
- 4. December: Only a lazy developer is a good developer - 4. Dezember 2024